package com.fingard.dsp.bank.directbank.yqb01;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Iterator;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import org.apache.commons.codec.binary.Base64;

import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.io.FileHelper;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class YQB01Base extends DirectBase {
	protected String getCharset() {
		return getBankConfig().getCharset("UTF-8");
	}
	
	/** map转HTTP请求串 */
	public String mapToUrlStr(Map<String, String> map) {
		StringBuilder sbuilder= new StringBuilder();
		Iterator<String> it = map.keySet().iterator();
		while(it.hasNext()) {
			String key = it.next();
			String value = map.get(key);
			if (sbuilder.length() > 0) {
				sbuilder.append("&");
			}
			sbuilder.append(key).append("=").append(value);
		}
		WriteBankLogLn2("待签名数据:\r\n" + sbuilder.toString());
		return sbuilder.toString();
	}

	/** RSA私钥签名   SignType:SHA256withRSA*/
	public String signWithRSA(ActSetItem actItem, String signData) throws Exception {
		try {
			byte[] encryptBytes = Base64.decodeBase64(FileHelper.readFileBytes(actItem.ownCertFilePath));
			KeyFactory keyfactory = KeyFactory.getInstance("RSA");
			PrivateKey prikey = keyfactory.generatePrivate(new PKCS8EncodedKeySpec(encryptBytes));
			Signature signature = Signature.getInstance("SHA256withRSA");
			signature.initSign(prikey);
			signature.update(signData.getBytes(getCharset()));
			return byte2hex(signature.sign());
		} catch (Exception ex) {
			WriteBankLogLn(ex);
			throw new Exception(ex);
		}
	}
	
	public String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; b != null && n < b.length; n++) {
			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
		}
		return hs;
	}

	/** RSA公钥验签 */
	public boolean verifyWithRSA(ActSetItem actSetItem, String verifyData, String signature) throws Exception {
		try {
			byte[] certTextBytes = Base64.decodeBase64(FileHelper.readFileBytes(actSetItem.oppCertFilePath));
			X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(certTextBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec);
			byte[] signBytes = hex2byte(signature.getBytes(getCharset()));
			Signature signatureChecker = Signature.getInstance("SHA256withRSA");
			signatureChecker.initVerify(pubKey);
			signatureChecker.update(verifyData.getBytes(getCharset()));
			return signatureChecker.verify(signBytes);
		} catch (Exception ex) {
			WriteBankLogLn(ex);
			throw new Exception(ex);
		}
	}
	
	public byte[] hex2byte(byte[] b) {
		if ((b.length % 2) != 0)
			throw new IllegalArgumentException("byte length is not correct");
		byte[] b2 = new byte[b.length / 2];
		for (int n = 0; n < b.length; n += 2) {
			String item = new String(b, n, 2);
			b2[n / 2] = (byte) Integer.parseInt(item, 16);
		}
		return b2;
	}
	
	/** AES加密 */
	public String encryptByAES(String saltKey, String encryptData) throws Exception {
		try {
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(getKeyByStr(saltKey));
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			keygen.init(secureRandom);
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, keygen.generateKey());
			return new BASE64Encoder().encode(cipher.doFinal(encryptData.getBytes(getCharset())));
		} catch (Exception ex) {
			WriteBankLogLn(ex);
			throw new Exception(ex);
		}
	}
	
	/** AES解密 */
	public String decryptByAES(String  saltKey, String decryptData) throws Exception {
		try {
			Cipher cipher = Cipher.getInstance("AES");
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(getKeyByStr(saltKey));
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			keygen.init(secureRandom);
			cipher.init(Cipher.DECRYPT_MODE, keygen.generateKey());
			byte[] decryptBytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(decryptData));
			return new String(decryptBytes, getCharset());
		} catch (Exception ex) {
			WriteBankLogLn(ex);
			throw new Exception(ex);
		}
	}

	public static byte[] getKeyByStr(String str) {
		byte[] bRet = new byte[str.length() / 2];
		for (int i = 0; i < str.length() / 2; i++) {
			Integer itg = new Integer(16 * getChrInt(str.charAt(2 * i))	+ getChrInt(str.charAt(2 * i + 1)));
			bRet[i] = itg.byteValue();
		}
		return bRet;
	}

	public static int getChrInt(char chr) {
		int iRet = 0;
		if (chr == "0".charAt(0))
			iRet = 0;
		if (chr == "1".charAt(0))
			iRet = 1;
		if (chr == "2".charAt(0))
			iRet = 2;
		if (chr == "3".charAt(0))
			iRet = 3;
		if (chr == "4".charAt(0))
			iRet = 4;
		if (chr == "5".charAt(0))
			iRet = 5;
		if (chr == "6".charAt(0))
			iRet = 6;
		if (chr == "7".charAt(0))
			iRet = 7;
		if (chr == "8".charAt(0))
			iRet = 8;
		if (chr == "9".charAt(0))
			iRet = 9;
		if (chr == "A".charAt(0))
			iRet = 10;
		if (chr == "B".charAt(0))
			iRet = 11;
		if (chr == "C".charAt(0))
			iRet = 12;
		if (chr == "D".charAt(0))
			iRet = 13;
		if (chr == "E".charAt(0))
			iRet = 14;
		if (chr == "F".charAt(0))
			iRet = 15;
		return iRet;
	}
}
